home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk23 / fastdisk / fd.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  25KB  |  1,054 lines

  1.  
  2. #include <exec/types.h>
  3. #include <exec/memory.h>
  4. #include <devices/trackdisk.h>
  5. #include <libraries/dos.h>
  6. #include <libraries/dosextens.h>
  7. #include <workbench/workbench.h>
  8. #include <workbench/startup.h>
  9. #include <workbench/icon.h>
  10.  
  11. /* Diskspezifische Daten */
  12.  
  13. #define NUMHEADS    2
  14. #define BLOCKSIZE    TD_SECTOR
  15. #define SIZE        (BLOCKSIZE/4)
  16. #define NUM_ENTRIES    (SIZE-51-5)
  17. #define NUMBLOCKS    (NUMCYLS * NUMHEADS * NUMSECS)
  18. #define ROOTBLOCK    (NUMBLOCKS / 2)
  19. #define NUMLONGS    (NUMBLOCKS / 32)
  20. #define SECS_PER_TRACK    (NUMSECS * NUMHEADS)
  21.  
  22. /* Diskblockparameter */
  23.  
  24. #define TYPE        0
  25. #define HEADER_KEY    1
  26. #define HIGHEST_SEQ    2
  27. #define    SEQ_NUM        2
  28. #define BLOCK_COUNT    2
  29. #define    DATA_SIZE    3
  30. #define    FIRST_DATA    4
  31. #define    NEXT_DATA    4
  32. #define CHECKSUM    5
  33. #define DIR_HASHTAB    6
  34. #define FH_ENDLIST    6
  35. #define FH_BLOCKLIST    (SIZE-51)
  36. #define BITMAPINDEX    (SIZE-49)
  37. #define NAME        (SIZE-20)
  38. #define CREATE_TICKS    (SIZE-5)
  39. #define HASHCHAIN    (SIZE-4)
  40. #define    PARENT        (SIZE-3)
  41. #define EXTENSION    (SIZE-2)
  42. #define SECONDARY_TYPE    (SIZE-1)
  43. #define    BITMAP_CHECKSUM    0
  44. #define NAMEOFFSET    NAME*4+1
  45. #define NAMELENGTH    NAME*4
  46.  
  47. /*    Diskblock-Typ Definitionen     */
  48.  
  49. #define T_SHORT        2
  50. #define T_DATA        8
  51. #define T_LIST        16
  52. #define ST_ROOT        1
  53. #define ST_DIR        2
  54. #define ST_FILE        -3
  55.  
  56. #define EMPTY        (unsigned long*) 0
  57. #define BLOCKED        (unsigned long*) 0xFFFFFFFF
  58.  
  59. #define SOURCE        0
  60. #define DESTINATION    1
  61.  
  62. /*    verwendete Betriebssytemroutinen : exec.library        */
  63.  
  64. extern void        *AllocMem();
  65. extern void        CloseLibrary();
  66. extern struct IOExtTD    *CreateExtIO();
  67. extern struct MsgPort    *CreatePort();
  68. extern void        DeleteExtIO();
  69. extern void        DeletePort();
  70. extern void        DoIO();    
  71. extern void        FreeMem();
  72. extern long        OpenDevice();
  73. extern struct Library    *OpenLibrary();
  74. extern void        SendIO();
  75. extern void        WaitIO();    
  76.  
  77. /*    verwendete Betriebssytemroutinen : icon.library        */
  78.  
  79. extern struct DiskObject    GetDiskObjekt();
  80. extern char*            FindToolType();
  81. extern void            FreeDiskObject();
  82.  
  83. /*    verwendete Betriebssytemroutinen : dos.library        */
  84.  
  85. extern struct MsgPort        *DeviceProc();
  86.  
  87. /*    Unsere Workbenchmessage    (von Aztec vordefiniert)    */
  88.  
  89. extern struct WBStartup        *WBenchMsg;
  90.  
  91. /*    Globale Variablen    */
  92.  
  93. struct Library        *IconBase;
  94. struct IOExtTD        *diskreq0,*diskreq1,*diskreq2;
  95. struct MsgPort        *diskport;
  96. struct DiskObject    *dop;
  97.  
  98. unsigned long    diskchangecount0,diskchangecount1;
  99. unsigned long    dirstack   [NUMBLOCKS];
  100. unsigned long    sectormap  [NUMBLOCKS];
  101. unsigned long    *buffermap [NUMBLOCKS];
  102. unsigned long    *readmap   [NUMBLOCKS];
  103. unsigned long    filestack  [NUMBLOCKS/2];
  104. unsigned short    trackmap   [NUMTRACKS];
  105. unsigned short    dirstackptr = 0,filestackptr = 0,smptr = ROOTBLOCK;
  106. unsigned short    wbflag = 0, formatflag = 1, fastloadflag = 1;
  107. unsigned long    seccount, rootoff = 2;
  108. unsigned long    *trackbuffer;
  109. unsigned long    *oldbuffer = NULL;
  110. unsigned long    sourcedrive = 0 ,destinationdrive = 1;
  111. char        sourcedevice[5] = "DF0:";
  112. char        destdevice[5] = "DF1:";
  113.  
  114. /*    Interne Funktionen    */
  115.  
  116. unsigned long    popdir(), popfile(), getfreesector();
  117. unsigned long    *allocbuffer();
  118. unsigned long     *GetSector();
  119. short        is_special();
  120.  
  121.  
  122. main(argc,argv)
  123. register int    argc;
  124. register char    *argv[];
  125. {
  126.     register short int     drivetype,i;
  127.     register char        *str;
  128.  
  129.     drivetype = SOURCE;
  130.     if (argc) {
  131.  
  132.         /* Aufruf vom CLI */
  133.  
  134.         for (i=1; i < argc; i++) {
  135.             if (scmp(argv[i],"NOFORMAT",8)) {
  136.                 formatflag = 0;
  137.             } else if (scmp(argv[i],"FASTDIR",7)) {
  138.                 fastloadflag = 0;
  139.             } else if (scmp(argv[i],"FROM",4)) {
  140.                 drivetype = SOURCE;
  141.             } else if (scmp(argv[i],"TO",2)) {
  142.                 drivetype = DESTINATION;
  143.             } else if (scmp(argv[i],"DF",2)) {
  144.                 if (drivetype == SOURCE) {
  145.                     sourcedrive = (ULONG) atoi(argv[i]+2);
  146.                     drivetype = DESTINATION;
  147.                 } else {
  148.                     destinationdrive = (ULONG) atoi(argv[i]+2);
  149.                 }
  150.             } else {
  151.                 printf("Usage   : %s [FROM] drive [TO] drive [NOFORMAT] [FASTDIR]\n",argv[0]);
  152.                 printf("Defaults: FROM df0: TO df1:\n");
  153.                 exit(0);
  154.             }
  155.         }
  156.     } else {
  157.  
  158.         /* Aufruf von Workbench */
  159.  
  160.         wbflag = 1;
  161.  
  162.         if (!(IconBase = OpenLibrary(ICONNAME,0L))) {
  163.             printf("Where is the Icon-Library ?\n");
  164.             error();
  165.         }
  166.         if (!(dop = GetDiskObject(WBenchMsg -> sm_ArgList -> wa_Name))) {
  167.             printf("Couldn't find Disk-Object!\n");
  168.             error();
  169.         }
  170.         if (str = FindToolType(dop -> do_ToolTypes, "NOFORMAT")) {
  171.             if (scmp(str,"ON",2)) {
  172.                 formatflag = 0;
  173.             }
  174.         }
  175.         if (str = FindToolType(dop -> do_ToolTypes, "FASTDIR")) {
  176.             if (scmp(str,"ON",2)) {
  177.                 fastloadflag = 0;
  178.             }
  179.         }
  180.         if (str = FindToolType(dop -> do_ToolTypes, "FROM")) {
  181.             if (scmp(str,"DF",2)) {
  182.                 sourcedrive = (ULONG) atoi(str+2);
  183.             }
  184.         }
  185.         if (str = FindToolType(dop -> do_ToolTypes, "TO")) {
  186.             if (scmp(str,"DF",2)) {
  187.                 destinationdrive = (ULONG) atoi(str+2);
  188.             }
  189.         }
  190.         FreeDiskObject(dop);        
  191.     }
  192.  
  193.     sourcedevice[2] = (char) ('0' + (char) sourcedrive);
  194.     destdevice[2] = (char) ('0' + (char) destinationdrive);
  195.     if (sourcedrive == destinationdrive) {
  196.         printf("Can't copy from df%1ld: to df%1ld: !\n");
  197.         error();
  198.     }
  199.     
  200.     openall ();
  201.  
  202.     printf("\n  FastDisk V1.5  -  Written 1987 by Torsten Stolpmann \n\n");
  203.     printf(" Please insert SOURCE      Disk in Drive df%1ld:\n",sourcedrive);
  204.     printf(" Please insert DESTINATION Disk in Drive df%1ld:\n",destinationdrive);
  205.     printf(" Press RETURN to continue\n");
  206.     getchar();
  207.  
  208.     checkdisks();
  209.     init ();
  210.     travel (ROOTBLOCK);
  211.     moveblock ();
  212.     sortfiles ();
  213.     makefiles ();
  214.     makedirs ();
  215.     makeroot ();
  216.     writeheaders ();
  217.     writeblank();
  218.     writeboot ();
  219.     closeall ();
  220. }
  221.  
  222. travel(head)
  223. unsigned long    head;
  224. {
  225.     register unsigned long    *headbuffer,*workbuffer,*auxbuffer;
  226.     register unsigned long    sector,hc;
  227.     register unsigned short    i,count;
  228.  
  229.     /*    Rekursives Durchlaufen des Directory-Trees in Zwischenordnung    */
  230.  
  231.     headbuffer = buffermap[head];
  232.     for (i=DIR_HASHTAB; i<=FH_BLOCKLIST; i++) {
  233.         sector=headbuffer[i];
  234.         if (sector) {
  235.             workbuffer = buffermap[sector] = GetSector(sector);
  236.             if ((workbuffer[TYPE] == T_SHORT) &&
  237.                 (workbuffer[SECONDARY_TYPE] == ST_DIR)) {
  238.                 if (fastloadflag) {
  239.                     sectormap[sector] = ROOTBLOCK+2+dirstackptr;
  240.                 } else {
  241.                     sectormap[sector] = smptr++;
  242.                 }
  243.                 pushdir(sector);
  244.                 travel(sector);
  245.             }
  246.             else {
  247.                 sectormap[sector] = smptr++;
  248.                 pushfile(sector);
  249.  
  250.                     /*    Existieren File List Blocks ?    */
  251.  
  252.                 auxbuffer = buffermap[sector];
  253.                 count = workbuffer[HIGHEST_SEQ];
  254.                 while (auxbuffer[EXTENSION]) {
  255.                     sector = auxbuffer[EXTENSION];
  256.                     auxbuffer = buffermap[sector] = GetSector(sector);
  257.                     count += auxbuffer[BLOCK_COUNT];
  258.                     sectormap[sector] = smptr++;
  259.                 }
  260.  
  261.                 /*    Ist es ein .info-File?    */
  262.  
  263.                 if (is_special(workbuffer)) {
  264.                     sectormap[workbuffer[FIRST_DATA]] = smptr;
  265.                     smptr += count;
  266.                 }
  267.             }
  268.  
  269.             /* Weitere Header-Blocks in der Hashchain ?     */
  270.  
  271.             hc=workbuffer[HASHCHAIN];
  272.             while (hc) {
  273.                 workbuffer = buffermap[hc] = GetSector(hc);
  274.                 if ((workbuffer[TYPE] == T_SHORT) &&
  275.                     (workbuffer[SECONDARY_TYPE] == ST_DIR)) {
  276.                     sectormap[hc] = ROOTBLOCK+2+dirstackptr;
  277.                     if (fastloadflag) {
  278.                         sectormap[hc] = ROOTBLOCK+2+dirstackptr;
  279.                     } else {
  280.                         sectormap[hc] = smptr++;
  281.                     }
  282.                     pushdir(hc);
  283.                     travel(hc);
  284.                 }
  285.                 else {
  286.                     sectormap[hc]=smptr++;
  287.                     pushfile(hc);
  288.  
  289.                     /*    Existieren File List Blocks ?    */
  290.  
  291.                     auxbuffer = buffermap[hc];
  292.                     count = workbuffer[HIGHEST_SEQ];
  293.                     while (auxbuffer[EXTENSION]) {
  294.                         sector = auxbuffer[EXTENSION];
  295.                         auxbuffer = buffermap[sector] = GetSector(sector);
  296.                         count += auxbuffer[BLOCK_COUNT];
  297.                         sectormap[sector] = smptr++;
  298.                     }
  299.  
  300.                     /*    Ist es ein .info-File ?        */
  301.  
  302.                     if (is_special(workbuffer)) {
  303.                         sectormap[workbuffer[FIRST_DATA]] = smptr;
  304.                         smptr += count;
  305.                     }
  306.                 }
  307.                 hc=workbuffer[HASHCHAIN];
  308.             }
  309.         }
  310.     }
  311. }
  312.  
  313. moveblock()
  314. {
  315.     register unsigned long    sector,dest;
  316.     register unsigned short diff;
  317.  
  318.     /*    Zentriert die Header-Blocks auf der Diskette    */
  319.  
  320.     if ((diff = (smptr-1-ROOTBLOCK)/SECS_PER_TRACK) > 2) {
  321.         diff = (((diff/2)+1) * SECS_PER_TRACK) - 2;
  322.     } else {
  323.         diff = 0;
  324.     }
  325.     if (fastloadflag) {
  326.         rootoff += dirstackptr;
  327.         diff -= dirstackptr;
  328.     }
  329.  
  330.     for (sector=2; sector < NUMBLOCKS; ++sector) {
  331.         dest = sectormap[sector];
  332.         if ((dest)
  333.          && (dest != ROOTBLOCK)
  334.          && (dest != ROOTBLOCK+1)
  335.          && !((fastloadflag) &&
  336.               (buffermap[sector][SECONDARY_TYPE] == ST_DIR))) {
  337.             if ((dest >= ROOTBLOCK+2) && (dest-diff < ROOTBLOCK+rootoff)) {
  338.                 sectormap[sector] -= (ULONG) (diff+rootoff);
  339.             } else {
  340.                 sectormap[sector] -= (ULONG) diff;                    }
  341.         }
  342.     }
  343.     seccount = (ULONG) ROOTBLOCK - diff;
  344. }
  345.  
  346. sortfiles()
  347. {
  348.     register short int    file,count,top;
  349.     register unsigned long    temp;
  350.  
  351.     /* Erst die .info-Files kopieren */
  352.  
  353.     top = filestackptr-1;
  354.     for (file = 0; file < top;file++) {
  355.         if (is_special(buffermap[filestack[file]])) {
  356.             temp = filestack[file];
  357.             for (count=file; count < top; count++) {
  358.                 filestack[count] = filestack[count+1];
  359.             }
  360.             filestack[top--] = temp;
  361.             file--;
  362.         }
  363.     }
  364. }
  365.  
  366. short scmp(s1,s2,len)
  367. register char    *s1, *s2;
  368. register short    len;
  369. {
  370.     register short    i;
  371.  
  372.     /* strcmp() ohne Beachtung von Upper-/Lower-Case */
  373.  
  374.     for (i=0; i <len; i++) {
  375.         if (toupper(*(s1++)) != *(s2++)) {
  376.             return (0);
  377.         }
  378.     }
  379.     return (1);
  380. }
  381.  
  382. short is_special(buffer)
  383. register unsigned char    *buffer;
  384. {
  385.  
  386.     /* Diese Files werden direkt hinter ihrem Headerblock abgelegt */
  387.  
  388.     if (fastloadflag) {
  389.         return (1);
  390.     }
  391.  
  392.     if (scmp(buffer+NAMEOFFSET+buffer[NAMELENGTH]-5,".INFO",5)) {
  393.         return (1);
  394.     }
  395.  
  396.     if (scmp(buffer+NAMEOFFSET,"SYSTEM-CONFIGURATION",20)) {
  397.         return (1);
  398.     }
  399.  
  400.     if (scmp(buffer+NAMEOFFSET,"STARTUP-SEQUENCE",16)) {
  401.         return (1);
  402.     }
  403.     return (0);
  404. }
  405.  
  406. unsigned long getfreesector()
  407. {
  408.  
  409.     /* Liefert naechsten freier Sector auf der Diskette */
  410.  
  411.     if (seccount == 2) {
  412.         return (seccount = NUMBLOCKS-1);
  413.     } else {
  414.         return (--seccount);
  415.     }
  416. }
  417.  
  418. makefiles()
  419. {
  420.     register unsigned long    file;
  421.  
  422.     /* kopiert alle File-Datenblocks auf die Zieldiskette.
  423.        Die neuen Sectorpositionen werden in den Headerblocks korrigiert. */
  424.  
  425.     while (file = popfile()) {
  426.         dofile(buffermap[file]);
  427.     }
  428. }
  429.  
  430. dofile(headbuffer)
  431. register unsigned long    *headbuffer;
  432. {
  433.     register unsigned long    *workbuffer;
  434.     register unsigned long    sector,next_sector,more_to_come;
  435.  
  436.     if (headbuffer[FIRST_DATA]) {
  437.         workbuffer = GetSector(headbuffer[FIRST_DATA]);
  438.         if (is_special(headbuffer)) {
  439.             sector = sectormap[headbuffer[FIRST_DATA]];
  440.             if (sector == ROOTBLOCK) {
  441.                 sector += rootoff;
  442.             }
  443.         } else {
  444.             sector = getfreesector();
  445.         }
  446.         sectormap[headbuffer[FIRST_DATA]] = sector;
  447.         do {
  448.             workbuffer[HEADER_KEY]=sectormap[headbuffer[HEADER_KEY]];
  449.             more_to_come = workbuffer[NEXT_DATA];
  450.             if (more_to_come) {
  451.                 if (is_special(headbuffer)) {
  452.                     next_sector = sector + 1;
  453.                     if (next_sector == ROOTBLOCK) {
  454.                         next_sector += rootoff;
  455.                     }
  456.                 } else {
  457.                     next_sector = getfreesector();
  458.                 }
  459.                 workbuffer[NEXT_DATA] = next_sector;
  460.             }
  461.             DoCheckSum(workbuffer,CHECKSUM);
  462.             PutSector(sector,workbuffer);
  463.             if (more_to_come) {
  464.                 workbuffer = GetSector(more_to_come);
  465.                 sector = sectormap[more_to_come] = next_sector;
  466.             }
  467.         } while (more_to_come);
  468.     }
  469.         /*    Aenderungen in File Header & File List Blocks    */
  470.  
  471.     do {
  472.         more_to_come = headbuffer[EXTENSION];
  473.         sector = FH_BLOCKLIST;
  474.         while (sector >= FH_ENDLIST) {
  475.             headbuffer[sector--]=sectormap[headbuffer[sector]];
  476.         }
  477.         headbuffer[PARENT]     = sectormap[headbuffer[PARENT]];
  478.         headbuffer[HEADER_KEY] = sectormap[headbuffer[HEADER_KEY]];
  479.         headbuffer[FIRST_DATA] = sectormap[headbuffer[FIRST_DATA]];
  480.         headbuffer[HASHCHAIN]  = sectormap[headbuffer[HASHCHAIN]];
  481.         headbuffer[EXTENSION]  = sectormap[headbuffer[EXTENSION]];
  482.         DoCheckSum(headbuffer,CHECKSUM);
  483.         if (more_to_come) {
  484.             headbuffer = buffermap[more_to_come];
  485.         }
  486.     } while (more_to_come);
  487. }
  488.  
  489. makedirs()
  490. {
  491.     register unsigned long    *headbuffer, sector, dir;
  492.  
  493.     /* Aenderungen in den Directory-Header Blocks */
  494.  
  495.     while (dir = popdir()) {
  496.         headbuffer = buffermap[dir];
  497.         for ( sector = FH_BLOCKLIST;
  498.               sector >= FH_ENDLIST;
  499.               --sector) {
  500.             if (headbuffer[sector]) {
  501.                 headbuffer[sector]=sectormap[headbuffer[sector]];
  502.             }
  503.         }
  504.         headbuffer[PARENT]     = sectormap[headbuffer[PARENT]];
  505.         headbuffer[HEADER_KEY] = sectormap[headbuffer[HEADER_KEY]];
  506.         headbuffer[HASHCHAIN]  = sectormap[headbuffer[HASHCHAIN]];
  507.         headbuffer[EXTENSION]  = sectormap[headbuffer[EXTENSION]];
  508.         DoCheckSum(headbuffer,CHECKSUM);
  509.     }
  510. }        
  511.  
  512. makeroot()
  513. {
  514.     register unsigned long    *headbuffer,*workbuffer;
  515.     register unsigned long    sector;
  516.     register unsigned long    bmsector,mask;
  517.     register unsigned short    offset,count;
  518.  
  519.     workbuffer = allocbuffer();
  520.     headbuffer = buffermap[ROOTBLOCK];
  521.  
  522.     /* Aenderungen im Rootblock */
  523.  
  524.     bmsector = sectormap[headbuffer[BITMAPINDEX]];
  525.     for ( sector = FH_BLOCKLIST; sector >= FH_ENDLIST; --sector) {
  526.         if (headbuffer[sector]) {
  527.             headbuffer[sector]=sectormap[headbuffer[sector]];
  528.         }
  529.     }
  530.     headbuffer[BITMAPINDEX] = bmsector;
  531.     headbuffer[CREATE_TICKS] += 1;    /* Wichtig ! Hiermit wird gesichert, */
  532.                     /* dass AmigaDOS Quell- und Zieldisk */
  533.                     /* unterscheiden kann. */
  534.     DoCheckSum(headbuffer,CHECKSUM);
  535.  
  536.     /* Neuen Bit-Map Sector erstellen */
  537.  
  538.     for (count=1; count <= NUMLONGS; ++count) {
  539.         workbuffer[count] = 0xFFFFFFFF;
  540.     }
  541.  
  542.     for (count = 2; count < NUMBLOCKS; ++count) {
  543.         sector = sectormap[count];
  544.         if (sector) {
  545.             offset = 1 + ((sector-2)/32);
  546.             mask   = (ULONG) 1 << ((sector-2) & 0x1f);
  547.             workbuffer[offset] -= (ULONG) mask;
  548.         }
  549.     }
  550.     DoCheckSum(workbuffer,BITMAP_CHECKSUM);
  551.     PutSector(bmsector,workbuffer);
  552. }
  553.  
  554. writeheaders()
  555. {
  556.     register unsigned short    buffer;
  557.  
  558.     /* Alle Header-Blocks werden auf Zieldisk geschrieben */
  559.  
  560.     for (buffer=0; buffer<NUMBLOCKS; ++buffer) {
  561.         dirstack[buffer] = NULL;
  562.     }
  563.  
  564.     for (buffer = 2; buffer<NUMBLOCKS; ++buffer) {
  565.         if (buffermap[buffer]) {
  566.             dirstack[sectormap[buffer]] = (ULONG) buffermap[buffer];
  567.             buffermap[buffer] = NULL;
  568.         }
  569.     }
  570.  
  571.     for (buffer = 0; buffer<NUMBLOCKS; ++buffer) {
  572.         if (dirstack[buffer]) {
  573.             PutSector((ULONG) buffer,dirstack[buffer]);
  574.         }
  575.     }
  576.     PutSector(NULL,NULL);
  577. }
  578.  
  579. writeblank()
  580. {
  581.     register short int    i;
  582.  
  583.     /* Formatiert nicht belegte Tracks auf der Zieldisk */
  584.  
  585.     if (formatflag) {
  586.         for (i=0; i < NUMTRACKS; i++) {
  587.             if ( !(trackmap[i])) {
  588.                 formattrack(i);
  589.                 WaitIO(diskreq2);
  590.                 trackmap[i]=1;
  591.             }
  592.         }
  593.     }
  594. }
  595.  
  596. writeboot()
  597. {
  598.     register unsigned long *workbuffer;
  599.  
  600.     /* Bootsectoren uebertragen */
  601.  
  602.     workbuffer = allocbuffer();
  603.     ReadSector (0L,workbuffer);
  604.     WriteSector(0L,workbuffer);
  605.     WaitIO(diskreq1);
  606.     ReadSector (1L,workbuffer);
  607.     WriteSector(1L,workbuffer);
  608.     WaitIO(diskreq1);
  609.     diskreq1 -> iotd_Req.io_Command = ETD_UPDATE;
  610.     diskreq1 -> iotd_Count        = diskchangecount1;
  611.     DoIO (diskreq1);
  612.     releasebuffer(workbuffer);
  613. }
  614.  
  615. init()
  616. {
  617.     register unsigned long    *headbuffer,*workbuffer,*buffer;
  618.     register unsigned long    count,offset,mask;
  619.  
  620.     /* Feldinitialisierungen */
  621.  
  622.     for (count=0L; count < NUMBLOCKS; ++count) {
  623.         sectormap [count] = NULL;
  624.         buffermap [count] = NULL;
  625.         dirstack  [count] = NULL;
  626.         readmap   [count] = EMPTY;
  627.     }
  628.     sectormap[0] = 0L;
  629.     sectormap[1] = 1L;
  630.  
  631.     /* Trackbuffer */
  632.  
  633.     for (count=0; count <= NUMTRACKS; count++) {
  634.         trackmap[count] = 0;
  635.     }
  636.  
  637.     if ( !(trackbuffer = AllocMem(NUMSECS * BLOCKSIZE, MEMF_CHIP | MEMF_CLEAR))) {
  638.         printf("Can't allocate Trackbuffer !\n");
  639.         error();
  640.     }
  641.  
  642.     /* Rootblock laden */
  643.  
  644.     smptr = ROOTBLOCK;
  645.     headbuffer = buffermap[ROOTBLOCK] = GetSector(ROOTBLOCK);
  646.     sectormap[ROOTBLOCK] = smptr++;
  647.     sectormap[headbuffer[BITMAPINDEX]] = smptr++;
  648.  
  649.     /* Markieren aller nicht belegter Bloecke (BAM-Selection) */
  650.  
  651.     workbuffer = GetSector(headbuffer[BITMAPINDEX]);
  652.     for (count = 2L; count < NUMBLOCKS; ++count) {
  653.         offset = 1L + ((count-2L)/32L);
  654.         mask   = 1L << ((count-2L) & 0x1fL);
  655.         if (workbuffer[offset] & mask) {
  656.             if (readmap[count]) {
  657.                 releasebuffer(readmap[count]);
  658.             }
  659.             readmap[count] = BLOCKED;
  660.         }
  661.     }
  662.     readmap[ROOTBLOCK] = readmap[headbuffer[BITMAPINDEX]] = BLOCKED;
  663.     readmap[0] = readmap[1] = BLOCKED;
  664.     releasebuffer(workbuffer);
  665. }
  666.  
  667. pushdir(sector)
  668. register unsigned long    sector;
  669. {
  670.     dirstack[dirstackptr++] = sector;
  671. }
  672.  
  673. unsigned long popdir()
  674. {
  675.     if ((dirstackptr) == 0)
  676.         return (NULL);
  677.     else
  678.         return (dirstack[--dirstackptr]);
  679. }
  680.  
  681. pushfile(sector)
  682. register unsigned long    sector;
  683. {
  684.     filestack[filestackptr++] = sector;
  685. }
  686.  
  687. unsigned long popfile()
  688. {
  689.     if ((filestackptr) == 0)
  690.         return (NULL);
  691.     else
  692.         return (filestack[--filestackptr]);
  693. }
  694.  
  695. DoCheckSum(buffer,pos)
  696. register unsigned long    *buffer;
  697. register unsigned short    pos;
  698. {
  699.     register unsigned long    count;
  700.     register unsigned long    checksum;
  701.  
  702.     /* CheckSum fuer normale und Bit-Map Blocks errechnen */
  703.  
  704.     buffer[pos] = checksum = NULL;
  705.     for (count=0; count < SIZE; ++count) {
  706.         checksum += (unsigned long) buffer[count];
  707.     }
  708.     buffer[pos] -= (unsigned long) checksum;
  709. }
  710.  
  711. ReadSector (sector,buffer)
  712. register unsigned long sector,*buffer;
  713. {
  714.     unsigned long    offset = sector * BLOCKSIZE;
  715.  
  716.     /* Laedt einen Sector von der Quell-Diskette */
  717.  
  718.     diskreq0 -> iotd_Req.io_Length     = BLOCKSIZE;      
  719.     diskreq0 -> iotd_Req.io_Data     = (APTR) buffer;    
  720.     diskreq0 -> iotd_Req.io_Command = ETD_READ;
  721.     diskreq0 -> iotd_Count         = diskchangecount0;
  722.     diskreq0 -> iotd_Req.io_Offset     = offset;
  723.     DoIO (diskreq0);
  724.     if (diskreq0 -> iotd_Req.io_Error) {
  725.         printf("Error %d while reading sector %4d from drive df%1ld: !\n",
  726.             (BYTE) diskreq0 -> iotd_Req.io_Error,
  727.             sector, sourcedrive);
  728.         error();
  729.     }
  730. }
  731.  
  732. unsigned long *GetSector(sector)
  733. register unsigned long    sector;
  734. {
  735.     register unsigned long    *workbuffer,*temp;
  736.     register unsigned long    track,sec;
  737.  
  738.     /* Holt einen Sector von der Quell-Diskette oder */
  739.     /* liefert den entsprechenden Buffer. */
  740.  
  741.     Chk_Abort();
  742.  
  743.     if (sector >= NUMBLOCKS) {
  744.         printf("Illegal sector detected, Disk in drive df%1ld: is corrupt !\n",
  745.             sourcedrive);
  746.         printf("Use diskdoctor to correct this disk.\n");
  747.         error();
  748.     }
  749.     if (readmap[sector]) {
  750.         if (readmap[sector] == BLOCKED) {
  751.             printf("Double Reference to sector %ld, disk in df%1ld: is corrupt !\n",
  752.                 sector,sourcedrive);
  753.             printf("Use diskdoctor to correct this disk.\n");
  754.             error();
  755.         } else {
  756.             temp = readmap[sector];
  757.             readmap[sector] = BLOCKED;
  758.             return (temp);
  759.         }
  760.     } else {
  761.         workbuffer = allocbuffer();
  762.         ReadSector (sector,workbuffer);
  763.         readmap[sector] = BLOCKED;
  764.         track = sector / SECS_PER_TRACK;
  765.         for (sec=track*SECS_PER_TRACK; sec < (track+1)*SECS_PER_TRACK; sec++) {
  766.             if (readmap[sec] == EMPTY) {
  767.                 if (readmap[sec] = allocbuffer()) {
  768.                     ReadSector(sec,readmap[sec]);
  769.                 } else {
  770.                     break;
  771.                 }
  772.             }
  773.         }
  774.         return (workbuffer);
  775.     }
  776. }
  777.  
  778. formattrack(track)
  779. register short int track;
  780. {
  781.  
  782.     /* Formatiert einen Track auf der Zieldiskette */
  783.  
  784.     Chk_Abort();
  785.  
  786.     diskreq2 -> iotd_Req.io_Length    = NUMSECS * BLOCKSIZE;      
  787.     diskreq2 -> iotd_Req.io_Data    = (APTR) trackbuffer;    
  788.     diskreq2 -> iotd_Req.io_Command = TD_FORMAT;
  789.     diskreq2 -> iotd_Count        = diskchangecount1;
  790.     diskreq2 -> iotd_Req.io_Offset    = track * NUMSECS * BLOCKSIZE;
  791.     SendIO (diskreq2);
  792.     if (diskreq1 -> iotd_Req.io_Error) {
  793.         printf("Error %ud while formatting Cylinder %2ud on Drive df%1ld: !\n",
  794.             (BYTE) diskreq2 -> iotd_Req.io_Error,
  795.             track/2, destinationdrive);
  796.         error();
  797.     }
  798. }
  799.  
  800. WriteSector(sector,buffer)
  801. register unsigned long sector;
  802. register unsigned long *buffer;
  803. {
  804.     register unsigned long    offset = sector * BLOCKSIZE;
  805.     register short int    track;
  806.  
  807.     /* Falls noch nicht geschehen, formatieren des Ziel-Tracks */
  808.  
  809.     track = (sector / NUMSECS);
  810.     if ( (formatflag) && !(trackmap[track])) {
  811.         formattrack(track);
  812.         trackmap[track] = 1;
  813.     }
  814.  
  815.     /* Schreibt einen Sector auf die Ziel-Diskette */
  816.  
  817.     diskreq1 -> iotd_Req.io_Length    = BLOCKSIZE;      
  818.     diskreq1 -> iotd_Req.io_Data    = (APTR) buffer;    
  819.     diskreq1 -> iotd_Req.io_Command = ETD_WRITE;
  820.     diskreq1 -> iotd_Count        = diskchangecount1;
  821.     diskreq1 -> iotd_Req.io_Offset    = offset;
  822.     SendIO (diskreq1); /* Asynchroner Schreibzugriff */
  823. }
  824.  
  825. PutSector(sector,buffer)
  826. register unsigned long sector;
  827. register unsigned long *buffer;
  828. {
  829.  
  830.     /* Schreibt Sector auf Zieldisk und deallociert den Buffer */
  831.  
  832.     if (oldbuffer) {
  833.         WaitIO(diskreq1); /* Warten auf das Ende des letzten Schreibzugriffs */
  834.         if (diskreq1 -> iotd_Req.io_Error) {
  835.             printf("Error %d while writing Sector %4ld to drive df%1ld: !\n",
  836.                 (BYTE) diskreq1 -> iotd_Req.io_Error,
  837.                 sector, destinationdrive);
  838.             error();
  839.         }
  840.         releasebuffer(oldbuffer);
  841.     }
  842.     if (oldbuffer = buffer) {
  843.         WriteSector(sector, buffer);
  844.     }
  845. }
  846.  
  847. unsigned long *allocbuffer()
  848. {
  849.     register unsigned long    *buffer;
  850.     register short int    sec;
  851.  
  852.     /* Allociert 512 Byte Chip-Memory als Sector-Buffer */
  853.     /* Falls kein Chip-Mem mehr vorhanden ist, wird ein */
  854.     /* bestehender, nicht unbedingt benoetigter Sector  */
  855.     /* deallociert.                     */
  856.  
  857.     buffer = AllocMem((long) BLOCKSIZE, MEMF_CHIP);
  858.     if (buffer == NULL) {
  859.         for (sec=2; sec<NUMBLOCKS; sec++) {
  860.             if ((readmap[sec]) && 
  861.                 (readmap[sec] != BLOCKED) &&
  862.                 (readmap[sec][TYPE] == T_DATA)) {
  863.                 buffer = readmap[sec];
  864.                 readmap[sec] = EMPTY;
  865.                 break;
  866.             }
  867.         }
  868.         if (sec == NUMBLOCKS) {
  869.             printf("Sorry, not enough CHIP-Memory to continue ...\n");
  870.             printf("Program terminated unsuccessfully.\n");
  871.             error();
  872.         }
  873.     }
  874.     return (buffer);
  875. }
  876.  
  877. releasebuffer(buffer)
  878. register unsigned long *buffer;
  879. {
  880.  
  881.     /* Deallociert einen 512-Byte Buffer */
  882.  
  883.     if (buffer) {
  884.         FreeMem(buffer, (long) BLOCKSIZE);
  885.     }
  886. }
  887.  
  888. openall()
  889. {
  890.     register unsigned long    err;
  891.  
  892.     /* Oeffnen der Disk-Devices */
  893.  
  894.     if ( !(diskport = CreatePort (NULL, NULL))) {
  895.         printf("Can't create DiskPort !\n");
  896.         error();
  897.     }
  898.  
  899.     if ( !(diskreq0 = CreateExtIO (diskport, (long) sizeof (*diskreq0)))) {
  900.         printf("Can't make IO block !\n");
  901.         error();
  902.     }
  903.  
  904.     if ( !(diskreq1 = CreateExtIO (diskport, (long) sizeof (*diskreq1)))) {
  905.         printf("Can't make IO block !\n");
  906.         error();
  907.     }
  908.  
  909.     if ( !(diskreq2 = CreateExtIO (diskport, (long) sizeof (*diskreq2)))) {
  910.         printf("Can't make IO block !\n");
  911.         error();
  912.     }
  913.  
  914.     if (err = OpenDevice (TD_NAME, sourcedrive, diskreq0, NULL)) {
  915.         printf ("Can't get drive %1ld, Error %ld.\n", sourcedrive, err);
  916.         error();
  917.     }
  918.  
  919.     if (err = OpenDevice (TD_NAME, destinationdrive, diskreq1, NULL)) {
  920.         printf ("Can't get drive %1ld, Error %ld\n", destinationdrive, err);
  921.         error();
  922.     }
  923.  
  924.     if (err = OpenDevice (TD_NAME, destinationdrive, diskreq2, NULL)) {
  925.         printf ("Can't get drive %1ld, Error %ld\n", destinationdrive, err);
  926.         error();
  927.     }
  928.  
  929.     /* Disk-Validation abstellen */
  930.  
  931.     dos_packet(DeviceProc(destdevice), ACTION_INHIBIT,
  932.            1L,0L,0L,0L,0L,0L,0L);
  933.  
  934.     dos_packet(DeviceProc(sourcedevice), ACTION_INHIBIT,
  935.            1L,0L,0L,0L,0L,0L,0L);
  936. }
  937.  
  938. checkdisks()
  939. {
  940.     diskreq0 -> iotd_Req.io_Command = TD_CHANGESTATE;
  941.     DoIO (diskreq0);
  942.     if (diskreq0 -> iotd_Req.io_Actual) {
  943.         printf("No Disk in Drive %1ld !\n",sourcedrive);
  944.         error();
  945.     }
  946.  
  947.     diskreq1 -> iotd_Req.io_Command = TD_CHANGESTATE;
  948.     DoIO (diskreq1);
  949.     if (diskreq1 -> iotd_Req.io_Actual) {
  950.         printf("No Disk in Drive %1ld !\n",destinationdrive);
  951.         error();
  952.     }
  953.  
  954.     diskreq1 -> iotd_Req.io_Command = TD_PROTSTATUS;
  955.     DoIO (diskreq1);
  956.     if (diskreq1 -> iotd_Req.io_Actual) {
  957.         printf("Disk in Drive %1ld is write-protected !\n",destinationdrive);
  958.         error();
  959.     }
  960.  
  961.     diskreq0 -> iotd_Req.io_Command = TD_CHANGENUM;
  962.     DoIO (diskreq0);
  963.     diskchangecount0 = diskreq0 -> iotd_Req.io_Actual;
  964.  
  965.     diskreq1 -> iotd_Req.io_Command = TD_CHANGENUM;
  966.     DoIO (diskreq1);
  967.     diskchangecount1 = diskreq1 -> iotd_Req.io_Actual;
  968.  
  969. }
  970.  
  971. Chk_Abort()
  972. {
  973.     if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
  974.         printf("F** BREAK\n");
  975.         error();
  976.     }
  977. }
  978.  
  979. error()
  980. {
  981.     closeall();
  982.     if (wbflag) {
  983.         printf("Press Return to abort.\n");
  984.         getchar();
  985.     }
  986.     exit(20);
  987. }
  988.  
  989. closeall()
  990. {
  991.     register unsigned long    count;
  992.  
  993.     /* Schliessen der Disk-Devices */
  994.     /* Deallocieren der Buffer     */
  995.     /* Schliessen der Library      */
  996.  
  997.     if (oldbuffer) {
  998.         releasebuffer(oldbuffer);
  999.     }
  1000.  
  1001.     for (count = NULL; count<NUMBLOCKS; ++count) {
  1002.         if (buffermap[count]) {
  1003.             releasebuffer(buffermap[count]);
  1004.         }
  1005.         if ((readmap[count]) && (readmap[count] != BLOCKED)) {
  1006.             releasebuffer(readmap[count]);
  1007.         } 
  1008.     }
  1009.  
  1010.     if (trackbuffer) {
  1011.         FreeMem(trackbuffer,NUMSECS * BLOCKSIZE);
  1012.     }
  1013.  
  1014.     if (diskreq0) {
  1015.         if (((long) diskreq0 -> iotd_Req.io_Device != -1L) &&
  1016.             ((long) diskreq0 -> iotd_Req.io_Device != 0L)) {
  1017.             CloseDevice (diskreq0);
  1018.         }
  1019.         DeleteExtIO (diskreq0, (long) sizeof (*diskreq0));
  1020.     }
  1021.  
  1022.     if (diskreq1) {
  1023.  
  1024.         if (((long) diskreq1 -> iotd_Req.io_Device != -1L) &&
  1025.             ((long) diskreq1 -> iotd_Req.io_Device != 0L)) {
  1026.             CloseDevice (diskreq1);
  1027.  
  1028.             /* Forced Diskchange im Destinationdrive */
  1029.  
  1030.             dos_packet(DeviceProc(destdevice), ACTION_INHIBIT,
  1031.                    0L,0L,0L,0L,0L,0L,0L);
  1032.  
  1033.             dos_packet(DeviceProc(sourcedevice), ACTION_INHIBIT,
  1034.                    0L,0L,0L,0L,0L,0L,0L);
  1035.         }
  1036.         DeleteExtIO (diskreq1, (long) sizeof (*diskreq1));
  1037.     }
  1038.  
  1039.     if (diskreq2) {
  1040.         if (((long) diskreq1 -> iotd_Req.io_Device != -1L) &&
  1041.             ((long) diskreq1 -> iotd_Req.io_Device != 0L)) {
  1042.             CloseDevice (diskreq2);
  1043.         }
  1044.         DeleteExtIO (diskreq2, (long) sizeof (*diskreq2));
  1045.     }
  1046.  
  1047.     if (diskport) {
  1048.         DeletePort (diskport);
  1049.     }
  1050.     if (IconBase) {
  1051.         CloseLibrary(IconBase);
  1052.     }
  1053. }
  1054.